use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use utoipa::ToSchema;
use std::collections::HashMap;

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct User {
    pub id: Uuid,
    pub username: String,
    pub avatar: Option<String>,
    pub openid: String,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct Language {
    pub id: Uuid,
    pub code: String, // e.g., "en", "zh-CN"
    pub name: String, // e.g., "English", "简体中文"
    pub is_default: bool,
    pub is_active: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct Category {
    pub id: Uuid,
    pub translations: Vec<CategoryTranslation>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct CategoryTranslation {
    pub id: Uuid,
    pub category_id: Uuid,
    pub language_code: String,
    pub name: String,
    pub description: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct Brand {
    pub id: Uuid,
    pub logo_url: Option<String>,
    pub website_url: Option<String>,
    pub translations: Vec<BrandTranslation>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct BrandTranslation {
    pub id: Uuid,
    pub brand_id: Uuid,
    pub language_code: String,
    pub name: String,
    pub description: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct Article {
    pub id: Uuid,
    pub slug: String,
    pub status: PublicationStatus,
    pub featured_image_url: Option<String>,
    pub published_at: Option<DateTime<Utc>>,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub translations: Vec<ArticleTranslation>,
    pub category_id: Option<Uuid>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ArticleTranslation {
    pub id: Uuid,
    pub article_id: Uuid,
    pub language_code: String,
    pub title: String,
    pub content: String,
    pub excerpt: Option<String>,
    pub meta_title: Option<String>,
    pub meta_description: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct Product {
    pub id: Uuid,
    pub sku: String,
    pub price: f64,
    pub compare_price: Option<f64>,
    pub cost_price: Option<f64>,
    pub track_inventory: bool,
    pub weight: Option<f64>,
    pub status: PublicationStatus,
    pub featured_image_url: Option<String>,
    pub published_at: Option<DateTime<Utc>>,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub translations: Vec<ProductTranslation>,
    pub category_id: Option<Uuid>,
    pub brand_id: Option<Uuid>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ProductTranslation {
    pub id: Uuid,
    pub product_id: Uuid,
    pub language_code: String,
    pub name: String,
    pub description: String,
    pub short_description: Option<String>,
    pub meta_title: Option<String>,
    pub meta_description: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum PublicationStatus {
    Draft,
    Published,
    Archived,
}

impl PublicationStatus {
    pub fn from_str(s: &str) -> Result<Self, ()> {
        match s {
            "draft" => Ok(PublicationStatus::Draft),
            "published" => Ok(PublicationStatus::Published),
            "archived" => Ok(PublicationStatus::Archived),
            _ => Err(()),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct FilterOptions {
    pub category_id: Option<Uuid>,
    pub brand_id: Option<Uuid>,
    pub keyword: Option<String>,
    pub status: Option<PublicationStatus>,
    pub language_code: Option<String>,
    pub page: Option<u32>,
    pub per_page: Option<u32>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct PaginatedResponse<T> {
    pub data: Vec<T>,
    pub pagination: Pagination,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct Pagination {
    pub page: u32,
    pub per_page: u32,
    pub total: u64,
    pub total_pages: u32,
}

// Request DTOs
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct CreateLanguageRequest {
    pub code: String,
    pub name: String,
    pub is_default: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct UpdateLanguageRequest {
    pub name: Option<String>,
    pub is_default: Option<bool>,
    pub is_active: Option<bool>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct CreateCategoryRequest {
    pub translations: Vec<CreateCategoryTranslationRequest>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct CreateCategoryTranslationRequest {
    pub language_code: String,
    pub name: String,
    pub description: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct UpdateCategoryRequest {
    pub translations: Vec<UpdateCategoryTranslationRequest>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct UpdateCategoryTranslationRequest {
    pub language_code: String,
    pub name: Option<String>,
    pub description: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct CreateBrandRequest {
    pub logo_url: Option<String>,
    pub website_url: Option<String>,
    pub translations: Vec<CreateBrandTranslationRequest>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct CreateBrandTranslationRequest {
    pub language_code: String,
    pub name: String,
    pub description: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct UpdateBrandRequest {
    pub logo_url: Option<String>,
    pub website_url: Option<String>,
    pub translations: Vec<UpdateBrandTranslationRequest>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct UpdateBrandTranslationRequest {
    pub language_code: String,
    pub name: Option<String>,
    pub description: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct CreateArticleRequest {
    pub slug: String,
    pub category_id: Option<Uuid>,
    pub featured_image_url: Option<String>,
    pub translations: Vec<CreateArticleTranslationRequest>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct CreateArticleTranslationRequest {
    pub language_code: String,
    pub title: String,
    pub content: String,
    pub excerpt: Option<String>,
    pub meta_title: Option<String>,
    pub meta_description: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct UpdateArticleRequest {
    pub slug: Option<String>,
    pub category_id: Option<Uuid>,
    pub featured_image_url: Option<String>,
    pub status: Option<PublicationStatus>,
    pub translations: Vec<UpdateArticleTranslationRequest>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct UpdateArticleTranslationRequest {
    pub language_code: String,
    pub title: Option<String>,
    pub content: Option<String>,
    pub excerpt: Option<String>,
    pub meta_title: Option<String>,
    pub meta_description: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct CreateProductRequest {
    pub sku: String,
    pub price: f64,
    pub compare_price: Option<f64>,
    pub cost_price: Option<f64>,
    pub track_inventory: bool,
    pub weight: Option<f64>,
    pub category_id: Option<Uuid>,
    pub brand_id: Option<Uuid>,
    pub featured_image_url: Option<String>,
    pub translations: Vec<CreateProductTranslationRequest>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct CreateProductTranslationRequest {
    pub language_code: String,
    pub name: String,
    pub description: String,
    pub short_description: Option<String>,
    pub meta_title: Option<String>,
    pub meta_description: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct UpdateProductRequest {
    pub sku: Option<String>,
    pub price: Option<f64>,
    pub compare_price: Option<f64>,
    pub cost_price: Option<f64>,
    pub track_inventory: Option<bool>,
    pub weight: Option<f64>,
    pub category_id: Option<Uuid>,
    pub brand_id: Option<Uuid>,
    pub featured_image_url: Option<String>,
    pub status: Option<PublicationStatus>,
    pub translations: Vec<UpdateProductTranslationRequest>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct UpdateProductTranslationRequest {
    pub language_code: String,
    pub name: Option<String>,
    pub description: Option<String>,
    pub short_description: Option<String>,
    pub meta_title: Option<String>,
    pub meta_description: Option<String>,
}

// Resource models
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct Resource {
    pub id: Uuid,
    pub file_name: String,
    pub extension: String,
    pub url: String,
    pub file_size: i64,
    pub mime_type: String,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ArticleResource {
    pub id: Uuid,
    pub article_id: Uuid,
    pub language_code: String,
    pub resource_id: Uuid,
    pub resource_type: String,
    pub sort_order: i32,
    pub resource: Resource,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ProductResource {
    pub id: Uuid,
    pub product_id: Uuid,
    pub language_code: String,
    pub resource_id: Uuid,
    pub resource_type: String,
    pub sort_order: i32,
    pub resource: Resource,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct UploadResponse {
    pub resources: Vec<Resource>,
    pub total_count: usize,
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ResourceAssignmentRequest {
    pub resource_id: Uuid,
    pub resource_type: String,
    pub sort_order: Option<i32>,
}

// Update existing models to include resources
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ArticleWithResources {
    pub id: Uuid,
    pub slug: String,
    pub status: PublicationStatus,
    pub featured_image_url: Option<String>,
    pub published_at: Option<DateTime<Utc>>,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub translations: Vec<ArticleTranslation>,
    pub category_id: Option<Uuid>,
    pub resources: HashMap<String, Vec<ArticleResource>>, // language_code -> resources
}

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ProductWithResources {
    pub id: Uuid,
    pub sku: String,
    pub price: f64,
    pub compare_price: Option<f64>,
    pub cost_price: Option<f64>,
    pub track_inventory: bool,
    pub weight: Option<f64>,
    pub status: PublicationStatus,
    pub featured_image_url: Option<String>,
    pub published_at: Option<DateTime<Utc>>,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub translations: Vec<ProductTranslation>,
    pub category_id: Option<Uuid>,
    pub brand_id: Option<Uuid>,
    pub resources: HashMap<String, Vec<ProductResource>>, // language_code -> resources
}